﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using TracyGUI.View;
using SharedLib.WinFormMVCFramework;
using Tracy.DataModel;
using TracyGUI.View.EntryTabs;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using SharedLib.Helpers;
using SharedLib;
using TracyGUI.Model;
using TracyGUI.View.UIComponent;

namespace TracyGUI.Controller.EntryTabs
{
    class MediaFileTabPageViewController : ControllerBase<IMediaFileTabPageView>, IController<IMediaFileTabPageView>, ITabPageViewController
    {
        ITabPageViewController _parent;
        protected override IMediaFileTabPageView ResolveView()
        {
            return Tracy.TracyFacade.Instance.DIContainer.Resolve<IMediaFileTabPageView>();
        }

        public MediaFileTabPageViewController(ITabPageViewController parent)
        {
            //Init
            _parent = parent;
            View.Name = "Files";
            View.Text = Tracy.TracyFacade.Instance.LanguageManager.GetText("MediaFileTabName");

            //View Events
            View.MediaFileExecuting += new EventHandler<SharedLib.EnhancedEventArgs>(View_MediaFileExecuting);
            View.ContainingFolderOpening += new EventHandler<SharedLib.GenericEventArgs<MediaFile>>(View_ContainingFolderOpening);
            View.OpenWithMenuGenerating += new EventHandler<SharedLib.GenericEventArgs<MediaFile>>(View_OpenWithMenuGenerating);
            View.MediaFilesChanging += new EventHandler<SharedLib.GenericEventArgs<List<MediaFile>>>(View_MediaFilesChanging);
            View.MediaFilesRemoving += new EventHandler<SharedLib.GenericEventArgs<List<MediaFile>>>(View_MediaFilesRemoving);

            //Model Events
            Tracy.TracyFacade.Instance.MediaFileProvider.ItemsAdded += new EventHandler<SharedLib.GenericEventArgs<IList<MediaFile>>>(MediaFileProvider_ItemsAdded);
            Tracy.TracyFacade.Instance.MediaFileProvider.ItemsRemoved += new EventHandler<SharedLib.GenericEventArgs<IList<MediaFile>>>(MediaFileProvider_ItemsRemoved);
            Tracy.TracyFacade.Instance.MediaFileProvider.ItemsChanged += new EventHandler<SharedLib.GenericEventArgs<IList<SharedLib.DataChangeSet<MediaFile>>>>(MediaFileProvider_ItemsChanged);
        
        }


        #region View Events
        void View_OpenWithMenuGenerating(object sender, SharedLib.GenericEventArgs<MediaFile> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                List<string> displayNameList = new List<string>();
                List<ProcessStartInfo> appInfoList = new List<ProcessStartInfo>();
                foreach (string appCmd in RegistryHelper.GetOpenWithList(e.Data.GetFileExtension()))
                {
                    string appDesc = appCmd;
                    string[] args = Win32Helper.SplitArgs(appCmd);
                    if (args != null && args.Length > 0)
                    {
                        string appPath = args[0];
                        if (File.Exists(appPath))
                        {
                            string desc = FileVersionInfo.GetVersionInfo(appPath).FileDescription;
                            if (!String.IsNullOrEmpty(desc))
                            {
                                displayNameList.Add(desc);
                                StringBuilder sbArgs = new StringBuilder();//Build up arguments string
                                for (int i = 1; i < args.Length; i++)
                                {
                                    string tmp = args[i];
                                    if (tmp == "%1") tmp = e.Data.GetSavedFilePath();
                                    if (tmp.Contains(" ") && !(tmp.StartsWith("\"") && tmp.StartsWith("\""))) tmp = "\"" + tmp + "\"";
                                    sbArgs.Append(tmp);
                                }

                                ProcessStartInfo psi = new ProcessStartInfo(appPath, sbArgs.ToString());
                                appInfoList.Add(psi);
                            }
                        }
                    }
                }

                View.SetOpenWithMenu(displayNameList, appInfoList);
            }, "UI Policy");
        }

        void View_MediaFileExecuting(object sender, SharedLib.EnhancedEventArgs e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                MediaFile file = (MediaFile)e.Attributes["file"];
                file = Tracy.TracyFacade.Instance.MediaFileProvider.GetItemByID(file.ID);
                ProcessStartInfo psi = (ProcessStartInfo)e.Attributes["processStartInfo"];
                if (CheckFileAvailablity(file))
                {
                    if (psi != null)
                        Process.Start(psi);
                    else
                        Process.Start(file.GetSavedFilePath());

                    if (file.Status != "Watched")
                    {
                        file.Status = "Watched";
                        Tracy.TracyFacade.Instance.MediaFileProvider.UpdateItem(file);
                    }
                }
            }, "UI Policy");
        }

        void View_MediaFilesChanging(object sender, SharedLib.GenericEventArgs<List<MediaFile>> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                Tracy.TracyFacade.Instance.MediaFileProvider.UpdateItems(e.Data);
            }, "UI Policy");
        }

        void View_MediaFilesRemoving(object sender, SharedLib.GenericEventArgs<List<MediaFile>> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                Tracy.TracyFacade.Instance.MediaFileProvider.RemoveItems(e.Data);
            }, "UI Policy");
        }

        void View_ContainingFolderOpening(object sender, SharedLib.GenericEventArgs<MediaFile> e)
        {
            Tracy.TracyFacade.Instance.ExceptionManager.Process(() =>
            {
                string path = Path.GetDirectoryName(e.Data.GetSavedFilePath());
                if (!Directory.Exists(path))
                {
                    path = Path.GetDirectoryName(Tracy.Properties.Settings.Default.DefaultDownloadFolder);
                }
                if (Directory.Exists(path))
                {
                    System.Diagnostics.Process.Start(path);
                }
            }, "UI Policy");
        }

        private bool CheckFileAvailablity(MediaFile file)
        {
            if (file.Status == "Ready" || file.Status == "Watched")
            {
                string filePath = file.GetSavedFilePath();
                if (filePath != null && File.Exists(filePath))
                {
                    return true;
                }
                else
                {
                    MessageBox.Show(Tracy.TracyFacade.Instance.LanguageManager.GetText("MessageBox_MediaFileNotFound_Message") + filePath);
                    file.Properties[MediaFile.KEY_PREVIOUS_STATUS] = file.Status;
                    file.Status = "Missing";
                    Tracy.TracyFacade.Instance.MediaFileProvider.UpdateItem(file);
                }
            }
            return false;
        }
        #endregion

        #region Model Events
        private bool IsMediaFileRelatedToCurrentView(MediaFile file)
        {
            if (file != null && file.Resource != null && file.Resource.Entry != null)
            {
                if (_parent is SingleEntryTabPageViewController)
                {
                    if (((SingleEntryTabPageViewController)_parent).Data.ID != file.Resource.Entry.ID) return false;
                }
                if (_parent is SearchResultTabPageViewController)
                {
                    if (!Tracy.TracyFacade.Instance.SearchEngine.IsMediaFileMatchingKeyword(file, ((SearchResultTabPageViewController)_parent).Keyword)) return false;
                }
                return true;
            }
            return false;
        }
        void MediaFileProvider_ItemsAdded(object sender, SharedLib.GenericEventArgs<IList<MediaFile>> e)
        {
            List<MediaFile> filesToAdd = new List<MediaFile>();
            foreach (MediaFile file in e.Data)
            {
                if (IsMediaFileRelatedToCurrentView(file)) filesToAdd.Add(file);
            }
            if (filesToAdd.Count > 0)
            {
                View.LoadDataItemsToListView(filesToAdd, false);
            }
        }

        void MediaFileProvider_ItemsChanged(object sender, SharedLib.GenericEventArgs<IList<SharedLib.DataChangeSet<MediaFile>>> e)
        {
            foreach (SharedLib.DataChangeSet<MediaFile> change in e.Data)
            {
                if (change.Data != null)
                {
                    if (IsMediaFileRelatedToCurrentView(change.Data))
                        View.UpdateDataItem(change.Data);
                }
            }
        }

        void MediaFileProvider_ItemsRemoved(object sender, SharedLib.GenericEventArgs<IList<MediaFile>> e)
        {
            List<MediaFile> filesToRemove = new List<MediaFile>();
            foreach (MediaFile file in e.Data)
            {
                if (IsMediaFileRelatedToCurrentView(file))
                    filesToRemove.Add(file);
            }
            View.RemoveDataItems(filesToRemove);
        }
        #endregion

        #region Public Functions
        public void LoadMediaFiles(List<MediaFile> mediaFiles, Func<bool> stopCondition, bool clearView = true)
        {
            if (mediaFiles.Count > 10) //Won't block UI
            {
                if(clearView && !stopCondition()) View.ClearListView();
                UIUpdateHelper.UpdateUIinTurn(50, mediaFiles, list => View.LoadDataItemsToListView(list, false), stopCondition);
            }
            else
            {
                View.LoadDataItemsToListView(mediaFiles, clearView);
            }
        }
        public void LoadMediaFiles(List<MediaFile> mediaFiles, bool clearView = true)
        {
            LoadMediaFiles(mediaFiles, () => false, clearView);
        }
        #endregion

        #region IController<ITabPageView> Members

        ITabPageView IController<ITabPageView>.View
        {
            get { return View; }
        }

        #endregion

        public void LoadViewState(ViewStateManager manager, System.Xml.XmlElement viewStateNode)
        {
            string sortColumn = viewStateNode.GetAttribute("sort-column");
            if (!string.IsNullOrEmpty(sortColumn))
            {
                View.ListViewItems.SetSortColumn(Convert.ToInt32(sortColumn), viewStateNode.GetAttribute("sort-order"));
            }
        }

        public void SaveViewState(ViewStateManager manager, System.Xml.XmlElement viewStateNode, System.Xml.XmlDocument doc)
        {
            var sorter = (ListViewColumnSorter)View.ListViewItems.ListViewItemSorter;
            if (sorter != null)
            {
                viewStateNode.SetAttribute("sort-column", sorter.SortColumn.ToString());
                viewStateNode.SetAttribute("sort-order", (sorter.Order == SortOrder.Ascending) ? "asc" : "desc");
            }
        }
    }
}
